import terraformerWkt from "terraformer-wkt-parser";

class GeoEntityManagerViewModel {
  constructor(viewer) {
    this.viewer = viewer;
    this.cacheEntityLayer = new Map();

    this.bsmFieldName = "tybsm";
    this.wktFieldName = "theGeom";
    this.crsSp = new Cesium.CRSSupport({
      wkt: 'PROJCS["CGCS2000_3_Degree_GK_CM_114E",GEOGCS["GCS_China_Geodetic_Coordinate_System_2000",DATUM["D_China_2000",SPHEROID["CGCS2000",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Gauss_Kruger"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",113.55],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0],AUTHORITY["EPSG",4547]]',
    });
  }

  destroy() {
    for (const [dlstflm, layer] of this.cacheEntityLayer) {
      layer.dispose();
    }
    this.cacheEntityLayer = null;
  }

  async addEntitys(geoEntitys) {
    let result = true;
    const tempMap = new Map();
    for (const geoEntity of geoEntitys) {
      if (geoEntity.dlstflm === undefined || geoEntity.dlstflm === null) {
        console.warn("dlstflm字段为空", geoEntity);
        result = false;
        continue;
      }
      if (tempMap.has(geoEntity.dlstflm)) {
        tempMap.get(geoEntity.dlstflm).push(geoEntity);
      } else {
        tempMap.set(geoEntity.dlstflm, [geoEntity]);
      }
    }
    for (const [dlstflm, geoEntityArr] of tempMap) {
      const layer = this.getEntityLayer(dlstflm);
      for (const geoEntity of geoEntityArr) {
        let entity = null;
        if (layer.cacheEntity.has(geoEntity[this.bsmFieldName])) {
          entity = layer.cacheEntity.get(geoEntity[this.bsmFieldName]);
        } else {
          entity = await this.entity2CesiumEntity(geoEntity, layer.entityColor);
          if (!entity) {
            result = false;
            continue;
          }
          layer.cacheEntity.set(geoEntity[this.bsmFieldName], entity);
        }
        entity && layer.addEntity(entity);
      }
    }
    return result;
  }

  removeEntitys(entitys) {
    const tempMap = new Map();
    for (const entity of entitys) {
      if (tempMap.has(entity.dlstflm)) {
        tempMap.get(entity.dlstflm).push(entity);
      } else {
        tempMap.set(entity.dlstflm, [entity]);
      }
    }
    for (const [dlstflm, geoEntityArr] of tempMap) {
      const layer = this.getEntityLayer(dlstflm);
      for (const geoEntity of geoEntityArr) {
        if (layer.cacheEntity.has(geoEntity[this.bsmFieldName])) {
          const entity = layer.cacheEntity.get(geoEntity[this.bsmFieldName]);
          layer.removeEntity(entity);
        }
      }
    }
  }

  clearAllEntitys() {
    for (const [dlstflm, layer] of this.cacheEntityLayer) {
      layer.removeAll();
    }
  }

  getEntityLayer(dlstflm) {
    if (this.cacheEntityLayer.has(dlstflm)) {
      return this.cacheEntityLayer.get(dlstflm);
    }
    const entityLayer = new agcim.layer.FeatureLayer(this.viewer);
    entityLayer.cacheEntity = new Map();
    entityLayer.entityColor = this.getRandomColor();
    this.cacheEntityLayer.set(dlstflm, entityLayer);
    return entityLayer;
  }

  async entity2CesiumEntity(entity, color) {
    let resultEntity = null;
    if (!entity[this.wktFieldName]) {
      console.error("wkt字段为空", entity, this.wktFieldName);
      return null;
    }
    try {
      const geojson = terraformerWkt.parse(entity[this.wktFieldName]);
      this.crsSp.coordinatesConverter(geojson);
      switch (geojson.type) {
        case "MultiLineString":
        case "LineString": {
          const dataSource = await Cesium.GeoJsonDataSource.load(geojson, {
            fill: color,
            stroke: color,
            strokeWidth: 3,
          });
          if (dataSource.entities?.values.length <= 0) {
            console.error("图形为空", entity);
            return null;
          }
          resultEntity = dataSource.entities.values[0];
          break;
        }
        case "Polygon":
        case "MultiPolygon": {
          const dataSource = await Cesium.GeoJsonDataSource.load(geojson, {
            fill: color,
            stroke: color,
            strokeWidth: 3,
          });
          if (dataSource.entities?.values.length <= 0) {
            console.error("图形为空", entity);
            return null;
          }
          resultEntity = dataSource.entities.values[0];
          resultEntity.polygon.heightReference = Cesium.HeightReference.RELATIVE_TO_GROUND;
          break;
        }
        case "Point": {
          // 用GeoJsonDataSource的话会创建成billboard
          resultEntity = new Cesium.Entity({
            position: Cesium.Cartesian3.fromDegrees(geojson.coordinates[0], geojson.coordinates[1]),
            point: {
              color: color,
            },
          });
          resultEntity.point.heightReference = Cesium.HeightReference.RELATIVE_TO_GROUND;
        }
        default:
          break;
      }
    } catch (error) {
      console.error(error);
      return null;
    }

    return resultEntity;
  }

  getRandomColor() {
    const cssColor = "#" + Math.floor(Math.random() * 16777215).toString(16);
    return Cesium.Color.fromCssColorString(cssColor);
  }
}

export default GeoEntityManagerViewModel;
